package com.google.code.netbuilder.services.equipment;

import com.google.code.netbuilder.util.ManagedObjectDataModel;
import com.google.code.netbuilder.dal.entities.Cable;
import com.google.code.netbuilder.dal.entities.Equipment;
import com.google.code.netbuilder.dal.entities.Port;
import com.google.code.netbuilder.dal.providers.ICableProvider;
import com.google.code.netbuilder.dal.providers.IEquipmentProvider;
import com.google.code.netbuilder.dal.providers.jpa.EquipmentProviderJPA;
import com.google.code.netbuilder.dal.services.ConnectionService;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.print.attribute.standard.Severity;



/**
 *
 * @author lyashenko_a_v
 */

@ManagedBean(name = "equipmentConnectionService")
@ViewScoped
public class EquipmentConnectionService implements Serializable {
    
    @EJB
    private IEquipmentProvider eqProvider;
    
    @EJB
    private ICableProvider cProvider;
    
    private List<Equipment> equipments;
    
    private List<Cable> cables;
    
    private ManagedObjectDataModel<Equipment> equipmentsDM;
    
    private ManagedObjectDataModel<Cable> cablesDM;
    
    private ManagedObjectDataModel<Port> leftPortsDM;
    
    private ManagedObjectDataModel<Port> rightPortsDM;
    
    private Equipment leftSelectedEquipment;
    
    private Equipment rightSelectedEquipment;
    
    private Cable selectedCable;
    
    private Port leftSelectedPort;
    
    private Port rightSelectedPort;
    
    @EJB
    private ConnectionService cs;
   

    public Port getLeftSelectedPort() {
        return leftSelectedPort;
    }

    public void setLeftSelectedPort(Port leftSelectedPort) {
        this.leftSelectedPort = leftSelectedPort;
    }

    public Port getRightSelectedPort() {
        return rightSelectedPort;
    }

    public void setRightSelectedPort(Port rightSelectedPort) {
        this.rightSelectedPort = rightSelectedPort;
    }
    


    public Equipment getLeftSelectedEquipment() {
        return leftSelectedEquipment;
    }

    public void setLeftSelectedEquipment(Equipment leftSelectedEquipment) {
        this.leftSelectedEquipment = leftSelectedEquipment;
        
        
        
    }

    public Equipment getRightSelectedEquipment() {
        return rightSelectedEquipment;
    }

    public void setRightSelectedEquipment(Equipment rightSelectedEquipment) {
        this.rightSelectedEquipment = rightSelectedEquipment;
        
        
    }

    public Cable getSelectedCable() {
        return selectedCable;
    }

    public void setSelectedCable(Cable selectedCable) {
        this.selectedCable = selectedCable;
    }
    
    

    public void setEquipments(List<Equipment> equipments) {
        this.equipments = equipments;
    }

    public void setCables(List<Cable> cables) {
        this.cables = cables;
    }  
    
    
    public List<Equipment> getEquipments() {
        return equipments;
    }
    
    public List<Cable> getCables() {
        return cables;
    }
    
    private void excludeFullOccupied() {
        if(equipments != null) {
            
            for(ListIterator<Equipment> i = equipments.listIterator(); i.hasNext(); ) {
            
                if(i.next().getNumOfFreePorts() <= 0) {
                
                    i.remove();
                }
            }
        }
        
        if(cables != null) {
            
            for(ListIterator<Cable> j = cables.listIterator(); j.hasNext(); ) {
                
                if(j.next().getNumOfFreeWires() <= 0) {
                    
                    j.remove();
                }
            }
        }
    }
    
    private List<Port> formPortLists(String key, Equipment eq) {
        if(eq != null && eq.getPorts() != null) {
            
            List<Port> resPorts = new ArrayList<Port>(eq.getPorts());
            String currentName = null;
            for(ListIterator<Port> i = resPorts.listIterator(); i.hasNext(); ) {
                
                currentName = i.next().getName();
                if(currentName == null || !currentName.startsWith(key)) {
                    
                    i.remove();
                }
            }
            return resPorts;
        }
        
        return null;
    }
    
    @PostConstruct
	public void afterInitialize() {
       
        equipments = eqProvider.findAll();
        cables = cProvider.findAll();
        excludeFullOccupied();
        
        if(equipments != null && !equipments.isEmpty()) {
            leftSelectedEquipment = equipments.get(0);
            rightSelectedEquipment = equipments.get(0);
        }
         
        
        
        if(cables != null && !cables.isEmpty()) {
            selectedCable = cables.get(0);
        }      
        
        equipmentsDM = new ManagedObjectDataModel<Equipment>(equipments);
        cablesDM = new ManagedObjectDataModel<Cable>(cables);
	}

    public ManagedObjectDataModel<Cable> getCablesDM() {
        return cablesDM;
    }

    public void setCablesDM(ManagedObjectDataModel<Cable> cablesDM) {
        this.cablesDM = cablesDM;
    }

    public ManagedObjectDataModel<Equipment> getEquipmentsDM() {
        return equipmentsDM;
    }

    public void setEquipmentsDM(ManagedObjectDataModel<Equipment> equipmentsDM) {
        this.equipmentsDM = equipmentsDM;
    }
    
    public void initializePorts()
    {
        
        leftPortsDM = new ManagedObjectDataModel<Port>(formPortLists("A-", leftSelectedEquipment));
        rightPortsDM = new ManagedObjectDataModel<Port>(formPortLists("B-", rightSelectedEquipment));
    }

    public ManagedObjectDataModel<Port> getLeftPortsDM() {
        return leftPortsDM;
    }

    public void setLeftPortsDM(ManagedObjectDataModel<Port> leftPortsDM) {
        this.leftPortsDM = leftPortsDM;
    }

    public ManagedObjectDataModel<Port> getRightPortsDM() {
        return rightPortsDM;
    }

    public void setRightPortsDM(ManagedObjectDataModel<Port> rightPortsDM) {
        this.rightPortsDM = rightPortsDM;
    }
    
    public void connect() {
        
        FacesMessage message;
        if(selectedCable == null) {
            
           message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!", "Cable not selected");
           FacesContext.getCurrentInstance().addMessage(null, message);
           return;
        }
        
        if(leftSelectedPort == null || rightSelectedPort == null) {
            
           message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!", "Not enough ports selected");
           FacesContext.getCurrentInstance().addMessage(null, message);
           return;
        }
        
        
        try {
            leftSelectedPort.setEquipment(leftSelectedEquipment);
            rightSelectedPort.setEquipment(rightSelectedEquipment);
            cs.createConnection(leftSelectedPort, rightSelectedPort, selectedCable);
            String detail = "Port '" + leftSelectedPort.getName() + "' of equipment '" +
                             leftSelectedEquipment.getName() + "' and port '" +
                             rightSelectedPort.getName() + "' of equipment '" +
                             rightSelectedEquipment.getName() + "' succesfully connected via cable '" +
                             selectedCable.getName() + "'.";
            message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", detail);
            FacesContext.getCurrentInstance().addMessage(null, message);
        }
        
        catch (IllegalArgumentException ex) {
            
            message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error!" , ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, message);
        }
        
        catch (Exception ex){
            
            message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Fatal Error!" , ex.getMessage());
            FacesContext.getCurrentInstance().addMessage(null, message);
            ex.printStackTrace();
        }
        
    }
}
